#!/usr/bin/env python
#
# Copyright 2011 Justin Bruce Van Horne <justinvh@gmail.com>
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

""" Handles texture browsing while in editor.

 TextureBrowser: Loads materials and displays tiles for selection.
"""

import pyglet
import json
import os

from time import time
from pyglet.window import key

from engine.material import Material
from engine.fixed_resolution import FixedResolutionViewport
from engine import camera

from shared import *

WIDTH, HEIGHT = (80, 300)


class TextureBrowser(pyglet.window.Window):
    """Handles loading and creating textures to be used by the map editor."""
    tiles = pyglet.graphics.Batch()
    tile_batch = []
    map_editor = None
    selected = None
    _mtr = {}
    mx, my = 50, 50
    pan_size = 8
    pan_sens = 16
    pan_enable = True
    scale = True
    scale_to = 32

    def __init__(self):
        """Initialize the material list."""
        super(TextureBrowser, self).__init__(WIDTH, HEIGHT)
        self.keys = key.KeyStateHandler()
        self.push_handlers(self.keys)
        self.camera = camera.FlatCamera(0, 0, WIDTH, HEIGHT)
        self.reload_tiles()

    def reload_tiles(self):
        files = os.listdir(MATERIAL_PATH)
        y = HEIGHT - 64

        # Clear previous tiles
        self.tiles = pyglet.graphics.Batch()
        map(lambda x: x.delete(), self.tile_batch)
        
        self.tile_batch = []
        prev_h, prev_w = 0, 0 
        for f in files:
            if not f[0].isalnum():
                print 'Skipping %s. You probably did not want this file.'
                continue
            name, ext = f.split(".")
            if ext != 'mtr':
                print 'Skipping %s. You probably did not want this file.'
                continue
            mtrs = json.load(open("%s/%s" % (MATERIAL_PATH, f)))
            for item in mtrs:
                if mtrs[item].get('entity'):
                    print 'Skipping entity (%s).' % item
                    continue
                mat = Material(mtrs[item], item, self.tiles)
                self.tile_batch.append(mat)

                if self.scale:
                    if mat.image.width > mat.image.height:
                        mat.scale = self.scale_to / float(mat.image.width)
                    else:
                        mat.scale = self.scale_to / float(mat.image.height)

                width = mat.image.width * mat.scale
                height = mat.image.height * mat.scale

                if (width + 8 + prev_w) < WIDTH:
                    mat.spawn(prev_w + 8, y)
                    prev_w += width + 8
                else:
                    y -= 8 + height
                    mat.spawn(0, y)
                    prev_w, prev_h = width, height
        self.total_height = -y

        if self.map_editor:
            self.map_editor.reload_tiles()

    def set_map_editor(self, editor):
        """Set the map editor."""
        self.map_editor = editor

    def on_mouse_motion(self, x, y, dx, dy):
        self.mx, self.my = x, y

    def on_mouse_press(self, x, y, button, modifiers):
        """Handles the selection of textures."""
        # If we already have a selected object make sure to restore
        # the object's opacity.
        if self.selected:
            self.selected.opacity = 255

        # No map editor
        if self.map_editor is None:
            return

        x = x + -self.camera.x
        y = y + -self.camera.y

        # Iterate to figure which tile we are clicking.
        for i, batch in enumerate(self.tile_batch):
            for j, tile in enumerate(batch.tiles):
                if (x > tile.x and y > tile.y and
                    x < (tile.width + tile.x) and
                    y < (tile.height + tile.y)):
                    self.selected = tile
                    self.selected.opacity = 155
                    self.map_editor.insert_mode(j)
                    return

        # Nothing found!
        self.selected = None
        self.dragging = False

    def on_mouse_leave(self, x, y):
        self.pan_enable = False

    def on_mouse_enter(self, x, y):
        self.pan_enable = True

    def on_key_press(self, pressed, modifier):
        if pressed:
            if pressed == key.EQUAL:
                if self.scale_to < 64:
                    self.scale_to += 8
            elif pressed == key.MINUS:
                if self.scale_to > 8:
                    self.scale_to -= 8
            elif pressed == key.S:
                self.scale = not self.scale
            self.reload_tiles()


    def on_draw(self):
        """Draw the tile list."""
        if self.pan_enable:
            if (HEIGHT - self.my) < self.pan_sens and self.camera.y > 0:
                self.camera.y -= self.pan_size
            elif self.my < self.pan_sens and self.camera.y < self.total_height:
                self.camera.y += self.pan_size

        self.clear()
        self.camera.project()
        self.tiles.draw()
